package jvmtest.RemoteExeDemo;
/**
 * Created with IntelliJ IDEA.
 *
 * @Author: Tom
 * @Date: 2022/02/08/11:03
 * @Description:
 */

import sun.security.util.Length;

/**
 *@ClassName ClassModifier
 *@Description
 *@Author 王琛
 *@Date 2022/2/8 11:03
 @Version 1.0
 */
public class ClassModifier {
    /**
     * Class 文件中常量池的起始偏移
     * */
    private static final int CONSTANT_POOL_COUNT_INDEX = 8;
    /**
     * CONSTANT_Utf8_info 常量的tag标志
     * */
    private static final int CONSTANT_Utf8_info = 1;
    /**
     * 常量池中11种常量所占的长度，CONSTANT_Utf8_info常量除外，因为它不是定长的
     * */
     private static final int[] CONSTANT_ITEM_LENGTH = { -1, -1, -1, 5, 5, 9, 9, 3, 3, 5, 5, 5, 5 };
     private static final int u1 = 1;
     private static final int u2 = 2;
     private byte[] classByte;
     public ClassModifier(byte[] classByte) { 
         this.classByte = classByte; 
     }
     /** 
     * @Description:  修改常量池中CONSTANT_Utf8_info常量的内容
     * @Param:   oldStr 修改前的字符串
     * @Param:   newStr 修改后的字符串
     * @return:  修改结果
     * @Author: 逗号
     * @Date: 2022/2/8 
     */
     public byte[] modifyUTF8Constants(String oldStr, String newStr){
         int cpc = getConstantPoolCount();
         int offset = CONSTANT_POOL_COUNT_INDEX + u2;
         for(int i = 0; i < cpc; i++) {
             int tag = ByteUtils.bytes2Int(classByte, offset, u1);
             if (tag == CONSTANT_Utf8_info) {
                 int len = ByteUtils.bytes2Int(classByte, offset + u1, u2);
                 offset += (u1 + u2);
                 String str = ByteUtils.bytes2string(classByte, offset, len);
                 if (str.equalsIgnoreCase(oldStr)) {
                     byte[] strBytes = ByteUtils.string2Bytes(newStr);
                     byte[] strLen = ByteUtils.int2Bytes(newStr.length(), u2);
                     classByte = ByteUtils.bytesReplace(classByte, offset - u2, u2, strLen);
                     classByte = ByteUtils.bytesReplace(classByte, offset, len, strBytes);
                     return classByte;
                 } else {
                     offset += len;
                 }
             } else {
                 offset += CONSTANT_ITEM_LENGTH[tag];
             }
         }
         return classByte;
     }

    private int getConstantPoolCount() {
         return ByteUtils.bytes2Int(classByte, CONSTANT_POOL_COUNT_INDEX, u2);
    }
}
